package com.ddd.mill.infrastructure.utils;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ddd.mill.infrastructure.persistent.domain.QnIPage;
import com.ddd.mill.infrastructure.persistent.domain.QnPage;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 类型转换工具
 */
public abstract class TypeConvertUtils {

    /**
     * 类型转换
     *
     * @param t     源对象
     * @param clazz 目标对象class
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> R convert(T t, Class<R> clazz) {
        R r = null;
        try {
            r = clazz.newInstance();
            BeanUtils.copyProperties(t, r);
        } catch (Exception e) {
        }
        return r;
    }

    /**
     * 类型转换
     *
     * @param tList 源对象List
     * @param clazz 目标对象class
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> convert(Collection<T> tList, Class<R> clazz) {
        List<R> rList = null;
        try {
            rList = new ArrayList<>();
            for (T t : tList) {
                R r = clazz.newInstance();
                BeanUtils.copyProperties(t, r);
                rList.add(r);
            }
        } catch (Exception e) {
        }
        return rList;
    }

    /**
     * List 转 Map
     *
     * @param vList     源List
     * @param fieldName 成为map的key的属性名
     * @param <K>       key的类型
     * @param <V>       value的类型
     * @return
     */
    public static <K, V> Map<K, V> convert(Collection<V> vList, String fieldName) {
        Map<K, V> map = new HashMap<>();
        for (V v : vList) {
            try {
                K key = (K) v.getClass().getDeclaredMethod("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1)).invoke(v);
                map.put(key, v);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * List 转 Map
     *
     * @param vList 源List
     * @param func  成为map的key
     * @param <K>   key的类型
     * @param <V>   value的类型
     * @return
     */
    public static <K, V> Map<K, V> convert(Collection<V> vList, Function<V, K> func) {
        if (vList == null) {
            return null;
        }
        return vList.stream().collect(Collectors.toMap(func, v -> v));
    }

    /**
     * List 转 Map<k,List<v>>
     *
     * @param vList     源List
     * @param fieldName 成为map的key的属性名
     * @param <K>       key的类型
     * @param <V>       value的类型
     * @return
     */
    public static <K, V> Map<K, List<V>> convertVL(Collection<V> vList, String fieldName) {
        Map<K, List<V>> map = new HashMap<>();
        for (V v : vList) {
            try {
                K key = (K) v.getClass().getDeclaredMethod("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1)).invoke(v);
                if (!map.containsKey(key)) {
                    List<V> list = new ArrayList<>();
                    list.add(v);
                    map.put(key, list);
                } else {
                    map.get(key).add(v);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * List 转 Map<k,List<v>>
     *
     * @param vList 源List
     * @param func  成为map的key的属性名
     * @param <K>   key的类型
     * @param <V>   value的类型
     * @return
     */
    public static <K, V> Map<K, List<V>> convertVL(Collection<V> vList, Function<V, K> func) {
        if (vList == null) {
            return null;
        }
        return vList.stream().collect(Collectors.groupingBy(func));
    }

    /**
     * List 转 Set
     *
     * @param tList     源List
     * @param fieldName 成为map的key的属性名
     * @param <T>       List的类型
     * @param <V>       value的类型
     * @return
     */
    public static <T, V> Set<V> convertToSet(Collection<T> tList, String fieldName) {
        Set<V> set = new HashSet<>();
        for (T t : tList) {
            try {
                V val = (V) t.getClass().getDeclaredMethod("get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1)).invoke(t);
                set.add(val);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return set;
    }

    /**
     * List 转 Set
     *
     * @param tList 源List
     * @param func  成为map的key的属性名
     * @param <T>   List的类型
     * @param <V>   value的类型
     * @return
     */
    public static <T, V> Set<V> convertToSet(Collection<T> tList, Function<T, V> func) {
        if (tList == null) {
            return null;
        }
        return tList.stream().map(func).collect(Collectors.toSet());
    }

//    /**
//     * IPage类型转换
//     *
//     * @param tIPage 原始IPage
//     * @param rc     目标类型的Class
//     * @param <T>    原始类型
//     * @param <R>    目标类型
//     * @return
//     */
//    public static <T, R> IPage<R> convert(IPage<T> tIPage, Class<R> rc) {
//        return tIPage.convert(t -> {
//            R r = null;
//            try {
//                r = rc.newInstance();
//            } catch (Exception e) {
//            }
//            BeanUtils.copyProperties(t, r);
//            return r;
//        });
//    }

    public static <T> QnIPage<T> convert(IPage<T> tIPage){
        QnIPage<T> qnPage = new QnPage<>();
        BeanUtils.copyProperties(tIPage, qnPage);
        return qnPage;
    }

    public static <T, R> QnIPage<R> convert(IPage<T> tIPage, Class<R> rc){
        QnIPage<R> qnPage = new QnPage<>();
        BeanUtils.copyProperties(tIPage, qnPage);
        qnPage.setRecords(convert(tIPage.getRecords(), rc));
        return qnPage;
    }
}
